<!DOCTYPE html>
<html lang="en">
<head>
    
    <meta charset="utf-8">
    <title>my-drag/src/Drag.vue - Documentation</title>
    
    
    <script src="scripts/prettify/prettify.js"></script>
    <script src="scripts/prettify/lang-css.js"></script>
    <link type="text/css" rel="stylesheet" href="styles/prettify.css">
    <link type="text/css" rel="stylesheet" href="styles/jsdoc.css">
    <script src="scripts/nav.js" defer></script>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>

<input type="checkbox" id="nav-trigger" class="nav-trigger" />
<label for="nav-trigger" class="navicon-button x">
  <div class="navicon"></div>
</label>

<label for="nav-trigger" class="overlay"></label>

<nav >
    
    <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Outline.html">Outline</a></li><li><a href="Tag.html">Tag</a></li><li><a href="TagCanvas.html">TagCanvas</a></li></ul><h3>Modules</h3><ul><li><a href="module-$ui_components_my-affix.html">$ui/components/my-affix</a></li><li><a href="module-$ui_components_my-anchor.html">$ui/components/my-anchor</a></li><li><a href="module-$ui_components_my-autocomplete.html">$ui/components/my-autocomplete</a></li><li><a href="module-$ui_components_my-avatar.html">$ui/components/my-avatar</a></li><li><a href="module-$ui_components_my-avatars.html">$ui/components/my-avatars</a></li><li><a href="module-$ui_components_my-back-top.html">$ui/components/my-back-top</a></li><li><a href="module-$ui_components_my-capture.html">$ui/components/my-capture</a><ul class='methods'><li data-type='method'><a href="module-$ui_components_my-capture.html#~_renderImg">_renderImg</a></li></ul></li><li><a href="module-$ui_components_my-card-list.html">$ui/components/my-card-list</a><ul class='methods'><li data-type='method'><a href="module-$ui_components_my-card-list.html#~refresh">refresh</a></li></ul></li><li><a href="module-$ui_components_my-cascader.html">$ui/components/my-cascader</a></li><li><a href="module-$ui_components_my-checkbox.html">$ui/components/my-checkbox</a></li><li><a href="module-$ui_components_my-clipboard.html">$ui/components/my-clipboard</a><ul class='methods'><li data-type='method'><a href="module-$ui_components_my-clipboard.html#~copy">copy</a></li></ul></li><li><a href="module-$ui_components_my-color-picker.html">$ui/components/my-color-picker</a></li><li><a href="module-$ui_components_my-contextmenu.html">$ui/components/my-contextmenu</a></li><li><a href="module-$ui_components_my-corner-mark.html">$ui/components/my-corner-mark</a></li><li><a href="module-$ui_components_my-crud.html">$ui/components/my-crud</a><ul class='methods'><li data-type='method'><a href="module-$ui_components_my-crud.html#~openAddDialog">openAddDialog</a></li><li data-type='method'><a href="module-$ui_components_my-crud.html#~refresh">refresh</a></li><li data-type='method'><a href="module-$ui_components_my-crud.html#~reload">reload</a></li></ul></li><li><a href="module-$ui_components_my-date.html">$ui/components/my-date</a></li><li><a href="module-$ui_components_my-date-picker.html">$ui/components/my-date-picker</a></li><li><a href="module-$ui_components_my-description.html">$ui/components/my-description</a></li><li><a href="module-$ui_components_my-detail.html">$ui/components/my-detail</a></li><li><a href="module-$ui_components_my-detail-item.html">$ui/components/my-detail-item</a></li><li><a href="module-$ui_components_my-dialog.html">$ui/components/my-dialog</a></li><li><a href="module-$ui_components_my-drag.html">$ui/components/my-drag</a><ul class='methods'><li data-type='method'><a href="module-$ui_components_my-drag.html#~getRelativeEl">getRelativeEl</a></li></ul></li><li><a href="module-$ui_components_my-drop.html">$ui/components/my-drop</a></li><li><a href="module-$ui_components_my-edit-tags.html">$ui/components/my-edit-tags</a></li><li><a href="module-$ui_components_my-editor.html">$ui/components/my-editor</a></li><li><a href="module-$ui_components_my-empty.html">$ui/components/my-empty</a></li><li><a href="module-$ui_components_my-filter.html">$ui/components/my-filter</a></li><li><a href="module-$ui_components_my-fixed.html">$ui/components/my-fixed</a><ul class='methods'><li data-type='method'><a href="module-$ui_components_my-fixed.html#~resize">resize</a></li></ul></li><li><a href="module-$ui_components_my-flex.html">$ui/components/my-flex</a></li><li><a href="module-$ui_components_my-flex-item.html">$ui/components/my-flex-item</a></li><li><a href="module-$ui_components_my-flip.html">$ui/components/my-flip</a></li><li><a href="module-$ui_components_my-float.html">$ui/components/my-float</a></li><li><a href="module-$ui_components_my-float-item.html">$ui/components/my-float-item</a></li><li><a href="module-$ui_components_my-form.html">$ui/components/my-form</a><ul class='methods'><li data-type='method'><a href="module-$ui_components_my-form.html#~reset">reset</a></li><li data-type='method'><a href="module-$ui_components_my-form.html#~submit">submit</a></li></ul></li><li><a href="module-$ui_components_my-form_src_Base.html">$ui/components/my-form/src/Base</a></li><li><a href="module-$ui_components_my-form_src_common_TagInput.html">$ui/components/my-form/src/common/TagInput</a></li><li><a href="module-$ui_components_my-form_src_common_TagSelect.html">$ui/components/my-form/src/common/TagSelect</a></li><li><a href="module-$ui_components_my-form_src_common_TreeSelect.html">$ui/components/my-form/src/common/TreeSelect</a></li><li><a href="module-$ui_components_my-header.html">$ui/components/my-header</a></li><li><a href="module-$ui_components_my-highlight.html">$ui/components/my-highlight</a></li><li><a href="module-$ui_components_my-icon.html">$ui/components/my-icon</a></li><li><a href="module-$ui_components_my-im-wall.html">$ui/components/my-im-wall</a></li><li><a href="module-$ui_components_my-input.html">$ui/components/my-input</a></li><li><a href="module-$ui_components_my-input-number.html">$ui/components/my-input-number</a></li><li><a href="module-$ui_components_my-layout.html">$ui/components/my-layout</a></li><li><a href="module-$ui_components_my-lazy.html">$ui/components/my-lazy</a></li><li><a href="module-$ui_components_my-list.html">$ui/components/my-list</a><ul class='methods'><li data-type='method'><a href="module-$ui_components_my-list.html#~load">load</a></li><li data-type='method'><a href="module-$ui_components_my-list.html#~refresh">refresh</a></li><li data-type='method'><a href="module-$ui_components_my-list.html#~reset">reset</a></li><li data-type='method'><a href="module-$ui_components_my-list.html#~scrollTop">scrollTop</a></li></ul></li><li><a href="module-$ui_components_my-location-picker.html">$ui/components/my-location-picker</a></li><li><a href="module-$ui_components_my-login.html">$ui/components/my-login</a><ul class='methods'><li data-type='method'><a href="module-$ui_components_my-login.html#~submit">submit</a></li></ul></li><li><a href="module-$ui_components_my-marquee.html">$ui/components/my-marquee</a><ul class='methods'><li data-type='method'><a href="module-$ui_components_my-marquee.html#~pause">pause</a></li><li data-type='method'><a href="module-$ui_components_my-marquee.html#~start">start</a></li><li data-type='method'><a href="module-$ui_components_my-marquee.html#~stop">stop</a></li></ul></li><li><a href="module-$ui_components_my-master-app.html">$ui/components/my-master-app</a><ul class='methods'><li data-type='method'><a href="module-$ui_components_my-master-app.html#~initState">initState</a></li><li data-type='method'><a href="module-$ui_components_my-master-app.html#~onStateChange">onStateChange</a></li><li data-type='method'><a href="module-$ui_components_my-master-app.html#~onStateChange">onStateChange</a></li><li data-type='method'><a href="module-$ui_components_my-master-app.html#~setState">setState</a></li></ul></li><li><a href="module-$ui_components_my-menu.html">$ui/components/my-menu</a></li><li><a href="module-$ui_components_my-micro-app.html">$ui/components/my-micro-app</a></li><li><a href="module-$ui_components_my-navbar.html">$ui/components/my-navbar</a></li><li><a href="module-$ui_components_my-navbar-FullScreenAction.html">$ui/components/my-navbar-FullScreenAction</a></li><li><a href="module-$ui_components_my-navbar-IconAction.html">$ui/components/my-navbar-IconAction</a></li><li><a href="module-$ui_components_my-navbar-UserAction.html">$ui/components/my-navbar-UserAction</a></li><li><a href="module-$ui_components_my-number.html">$ui/components/my-number</a></li><li><a href="module-$ui_components_my-panel.html">$ui/components/my-panel</a></li><li><a href="module-$ui_components_my-paragraph.html">$ui/components/my-paragraph</a></li><li><a href="module-$ui_components_my-pro.html">$ui/components/my-pro</a><ul class='methods'><li data-type='method'><a href="module-$ui_components_my-pro.html#~addTab">addTab</a></li><li data-type='method'><a href="module-$ui_components_my-pro.html#~closeTabs">closeTabs</a></li><li data-type='method'><a href="module-$ui_components_my-pro.html#~setTab">setTab</a></li></ul></li><li><a href="module-$ui_components_my-promise.html">$ui/components/my-promise</a></li><li><a href="module-$ui_components_my-radial-menu.html">$ui/components/my-radial-menu</a></li><li><a href="module-$ui_components_my-radio.html">$ui/components/my-radio</a></li><li><a href="module-$ui_components_my-range.html">$ui/components/my-range</a></li><li><a href="module-$ui_components_my-rate.html">$ui/components/my-rate</a></li><li><a href="module-$ui_components_my-resize.html">$ui/components/my-resize</a></li><li><a href="module-$ui_components_my-result.html">$ui/components/my-result</a></li><li><a href="module-$ui_components_my-revolve.html">$ui/components/my-revolve</a><ul class='methods'><li data-type='method'><a href="module-$ui_components_my-revolve.html#~next">next</a></li><li data-type='method'><a href="module-$ui_components_my-revolve.html#~prev">prev</a></li><li data-type='method'><a href="module-$ui_components_my-revolve.html#~start">start</a></li><li data-type='method'><a href="module-$ui_components_my-revolve.html#~stop">stop</a></li></ul></li><li><a href="module-$ui_components_my-search-box.html">$ui/components/my-search-box</a></li><li><a href="module-$ui_components_my-select.html">$ui/components/my-select</a></li><li><a href="module-$ui_components_my-sidebar.html">$ui/components/my-sidebar</a></li><li><a href="module-$ui_components_my-skeleton.html">$ui/components/my-skeleton</a></li><li><a href="module-$ui_components_my-slider.html">$ui/components/my-slider</a></li><li><a href="module-$ui_components_my-sortable.html">$ui/components/my-sortable</a></li><li><a href="module-$ui_components_my-spin.html">$ui/components/my-spin</a></li><li><a href="module-$ui_components_my-stat-card.html">$ui/components/my-stat-card</a></li><li><a href="module-$ui_components_my-switch.html">$ui/components/my-switch</a></li><li><a href="module-$ui_components_my-table.html">$ui/components/my-table</a><ul class='methods'><li data-type='method'><a href="module-$ui_components_my-table.html#~refresh">refresh</a></li></ul></li><li><a href="module-$ui_components_my-tabs.html">$ui/components/my-tabs</a></li><li><a href="module-$ui_components_my-tag-canvas.html">$ui/components/my-tag-canvas</a></li><li><a href="module-$ui_components_my-tag-input.html">$ui/components/my-tag-input</a></li><li><a href="module-$ui_components_my-tag-select.html">$ui/components/my-tag-select</a></li><li><a href="module-$ui_components_my-text.html">$ui/components/my-text</a></li><li><a href="module-$ui_components_my-timer.html">$ui/components/my-timer</a><ul class='methods'><li data-type='method'><a href="module-$ui_components_my-timer.html#~reset">reset</a></li><li data-type='method'><a href="module-$ui_components_my-timer.html#~start">start</a></li><li data-type='method'><a href="module-$ui_components_my-timer.html#~stop">stop</a></li></ul></li><li><a href="module-$ui_components_my-title.html">$ui/components/my-title</a></li><li><a href="module-$ui_components_my-tree-select.html">$ui/components/my-tree-select</a></li><li><a href="module-$ui_components_my-typography.html">$ui/components/my-typography</a></li><li><a href="module-$ui_components_my-water-fall.html">$ui/components/my-water-fall</a></li><li><a href="module-$ui_components_my-watermark.html">$ui/components/my-watermark</a></li><li><a href="module-$ui_components_my-wave.html">$ui/components/my-wave</a></li><li><a href="module-$ui_components_my-wrapper.html">$ui/components/my-wrapper</a></li><li><a href="module-widgets_my-print.html">widgets/my-print</a></li></ul><h3>Events</h3><ul><li><a href="module-$ui_components_my-stat-card.html#~event:action">action</a></li><li></li><li><a href="module-$ui_components_my-form_src_common_TagInput.html#~event:add">add</a></li><li><a href="module-$ui_components_my-wrapper.html#~event:back">back</a></li><li><a href="module-$ui_components_my-dialog.html#~event:cancel">cancel</a></li><li><a href="module-$ui_components_my-typography.html#~event:change">change</a></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li><a href="module-$ui_components_my-radial-menu.html#~event:click">click</a></li><li></li><li></li><li></li><li></li><li></li><li></li><li><a href="module-$ui_components_my-avatars.html#~event:click-add">click-add</a></li><li><a href="module-$ui_components_my-avatars.html#~event:click-item">click-item</a></li><li><a href="module-$ui_components_my-avatars.html#~event:click-more">click-more</a></li><li><a href="module-$ui_components_my-radial-menu.html#~event:close">close</a></li><li></li><li><a href="module-$ui_components_my-pro.html#~event:collapse">collapse</a></li><li><a href="module-$ui_components_my-form_src_common_TagSelect.html#~event:collapsed">collapsed</a></li><li><a href="module-$ui_components_my-table.html#~event:column-change">column-change</a></li><li><a href="module-$ui_components_my-navbar-UserAction.html#~event:command">command</a></li><li></li><li></li><li><a href="global.html#event:complete">complete</a></li><li></li><li><a href="module-$ui_components_my-typography.html#event:copy">copy</a></li><li></li><li></li><li></li><li></li><li><a href="module-$ui_components_my-drag.html#~event:drag">drag</a></li><li></li><li><a href="module-$ui_components_my-dialog.html#~event:drag-start">drag-start</a></li><li><a href="module-$ui_components_my-dialog.html#~event:drag-stop">drag-stop</a></li><li><a href="module-$ui_components_my-drop.html#~event:drop">drop</a></li><li><a href="module-$ui_components_my-typography.html#event:edited">edited</a></li><li></li><li></li><li></li><li></li><li><a href="module-$ui_components_my-typography.html#event:editing">editing</a></li><li></li><li></li><li></li><li></li><li><a href="module-$ui_components_my-drop.html#~event:enter">enter</a></li><li><a href="module-$ui_components_my-table.html#~event:error">error</a></li><li></li><li></li><li></li><li></li><li><a href="module-$ui_components_my-typography.html#event:expand">expand</a></li><li></li><li></li><li></li><li></li><li><a href="module-$ui_components_my-timer.html#~event:finish">finish</a></li><li><a href="module-$ui_components_my-dialog.html#~event:hide">hide</a></li><li><a href="module-$ui_components_my-lazy.html#~event:init">init</a></li><li><a href="module-$ui_components_my-form_src_common_TagInput.html#~event:input-change">input-change</a></li><li><a href="module-$ui_components_my-drop.html#~event:leave">leave</a></li><li><a href="module-$ui_components_my-wrapper.html#~event:link-click">link-click</a></li><li><a href="module-$ui_components_my-dialog.html#~event:load">load</a></li><li><a href="module-$ui_components_my-revolve.html#~event:loaded">loaded</a></li><li><a href="module-$ui_components_my-dialog.html#~event:maximize">maximize</a></li><li><a href="module-$ui_components_my-im-wall.html#~event:on-added">on-added</a></li><li><a href="module-$ui_components_my-capture.html#~event:on-capture">on-capture</a></li><li><a href="global.html#event:on-change">on-change</a></li><li><a href="module-$ui_components_my-tag-canvas.html#~event:on-click">on-click</a></li><li><a href="module-$ui_components_my-capture.html#~event:on-output">on-output</a></li><li><a href="module-$ui_components_my-radial-menu.html#~event:open">open</a></li><li></li><li><a href="module-$ui_components_my-drop.html#~event:over">over</a></li><li><a href="global.html#~event:page-change">page-change</a></li><li></li><li></li><li><a href="module-$ui_components_my-login.html#~event:pki">pki</a></li><li><a href="module-$ui_components_my-revolve.html#~event:progress">progress</a></li><li><a href="module-$ui_components_my-form_src_common_TagInput.html#~event:remove">remove</a></li><li><a href="module-$ui_components_my-timer.html#~event:reset">reset</a></li><li></li><li><a href="module-$ui_components_my-resize.html#~event:resize">resize</a></li><li></li><li><a href="module-$ui_components_my-dialog.html#~event:resize-start">resize-start</a></li><li><a href="module-$ui_components_my-dialog.html#~event:resize-stop">resize-stop</a></li><li><a href="module-$ui_components_my-search-box.html#~event:search">search</a></li><li><a href="module-$ui_components_my-sidebar.html#~event:select">select</a></li><li></li><li></li><li></li><li><a href="module-$ui_components_my-dialog.html#~event:show">show</a></li><li><a href="global.html#~event:size-change">size-change</a></li><li></li><li></li><li><a href="module-$ui_components_my-timer.html#~event:start">start</a></li><li></li><li></li><li></li><li><a href="module-$ui_components_my-timer.html#~event:stop">stop</a></li><li></li><li></li><li></li><li><a href="module-$ui_components_my-login.html#~event:submit">submit</a></li><li></li><li></li><li><a href="module-$ui_components_my-table.html#~event:success">success</a></li><li></li><li></li><li></li><li></li><li></li><li><a href="module-$ui_components_my-panel.html#~event:tab-change">tab-change</a></li><li><a href="module-$ui_components_my-pro.html#~event:tab-remove">tab-remove</a></li><li><a href="module-$ui_components_my-pro.html#~event:tab-select">tab-select</a></li><li><a href="module-$ui_components_my-timer.html#~event:tick">tick</a></li><li><a href="module-$ui_components_my-form.html#~event:validate">validate</a></li><li><a href="module-widgets_my-back-top.html#event:click">click</a></li></ul><h3>Global</h3><ul><li><a href="global.html#AddShadowToImage">AddShadowToImage</a></li><li><a href="global.html#appendChildNode">appendChildNode</a></li><li><a href="global.html#createEllipsisContainer">createEllipsisContainer</a></li><li><a href="global.html#createEllipsisContentHolder">createEllipsisContentHolder</a></li><li><a href="global.html#destroyVue">destroyVue</a></li><li><a href="global.html#getData">getData</a></li><li><a href="global.html#inRange">inRange</a></li><li><a href="global.html#instanceVue">instanceVue</a></li><li><a href="global.html#props">props</a></li><li><a href="global.html#pxToNumber">pxToNumber</a></li><li><a href="global.html#removeEllipsisContainer">removeEllipsisContainer</a></li><li><a href="global.html#RoundImage">RoundImage</a></li><li><a href="global.html#scrollTop">scrollTop</a></li><li><a href="global.html#setData">setData</a></li><li><a href="global.html#styleToString">styleToString</a></li><li><a href="global.html#wrapperDecorations">wrapperDecorations</a></li></ul>
</nav>

<div id="main">
    
    <h1 class="page-title">my-drag/src/Drag.vue</h1>
    

    



    
    <section>
        <article>
            <pre class="prettyprint source linenums"><code>&lt;template>
  &lt;div class="my-drag" :class="classes">
    &lt;slot>&lt;/slot>
  &lt;/div>
&lt;/template>

&lt;script>

  /**
   * 元素拖拽组件
   * @module $ui/components/my-drag
   */

  import {on, off, once, addClass, removeClass, setStyle, getStyle} from 'element-ui/lib/utils/dom'
  import {throttle} from '$ui/utils/util'
  import bus from '$ui/utils/bus'


  /**
   * 通过选择器、元素对象、函数获取元素对象
   * @private
   * @param {HTMLElement} el 容器元素
   * @param {HTMLElement|String|Function|*} selector
   * @return {HTMLElement}
   */
  function getElement(el, selector) {
    const type = typeof selector
    if (type === 'function') {
      return selector()
    } else if (type === 'string') {
      return el.querySelector(selector)
    } else if (selector instanceof HTMLElement) {
      return selector
    }
    return null
  }

  /**
   * 获取元素的尺寸宽高，支持对隐藏元素获取
   * @private
   * @param {HTMLElement} el
   * @return {{width: number, height: number}}
   */
  function getDomSize(el) {
    const clone = el.cloneNode(true)
    setStyle(clone, {
      visibility: 'hidden',
      display: 'inline-block'
    })
    document.body.appendChild(clone)
    const rect = clone.getBoundingClientRect()
    clone.parentNode.removeChild(clone)
    return {
      width: rect.width,
      height: rect.height
    }
  }

  /**
   *  获取拖拽元素相对位置参考元素
   */
  function getRelativeEl(el) {
    let parent = el.parentNode
    while (parent !== document.documentElement &amp;&amp; getStyle(parent, 'position') === 'static') {
      parent = parent.parentNode
    }
    return parent
  }


  // 默认拖拽范围设置
  const DEFAULT_RANGE = {
    left: -10000,
    top: -10000,
    width: 20000,
    height: 20000
  }

  // 拖拽句柄样式名
  const HANDLE_CLASS = 'my-drag__handle'

  /**
   * 插槽
   * @member slots
   * @property {string} default 默认插槽，定义内容
   */
  export default {
    name: 'MyDrag',

    /**
     * 属性参数
     * @member props
     * @property {String|HTMLElement|Function} handle 拖拽句柄元素，默认组件根元素，支持选择器、元素对象和函数，函数必须返回元素对象
     * @property {String} [axis] 限制拖拽方向可选: v 垂直、h 水平，默认不限制
     * @property {number} [delay=100] 延时开始拖拽
     * @property {Object|Function} [range] 限制拖拽范围, 默认不限制, 对象属性包含(left,top,width,height)，函数必须返回这个对象
     * @property {String|HTMLElement|Function} [target] 在目标元素范围内拖拽，支持选择器、元素对象和函数，函数必须返回元素对象
     * @property {Boolean|Function} [clone] 是否克隆拖拽元素, 函数可自定义克隆元素
     * @property {Boolean} [revert] 拖拽放置后动画返回原来位置，clone为true时才有效
     * @property {String} [group] 分组名称， 与my-drop配合使用
     * @property {Boolean} [disabled] 是否禁用拖拽
     * @property {*} [data] 附加数据
     * @property {string} [cloneClass]  克隆元素添加 className
     * @property {String|HTMLElement|Function} [origin] 原点元素，默认自动获取，支持选择器、元素对象和函数，函数必须返回元素对象
     * @property {Boolean} [appendBody] 克隆的节点是否加到body
     */
    props: {
      // 拖拽句柄元素，不设置就是自身
      handle: [String, HTMLElement, Function],
      // 限制拖拽方向可选: v 垂直、h 水平，默认不限制
      axis: {
        type: String,
        default: '',
        validator(val) {
          return ['', 'v', 'h'].includes(val)
        }
      },
      // 延时开始拖拽
      delay: {
        type: Number,
        default: 100
      },
      // 限制拖拽范围, 默认不限制
      range: [Object, Function],

      // 在目标元素范围内
      target: [String, HTMLElement, Function],
      // 是否克隆拖拽
      clone: [Boolean, Function],
      // 拖拽放置后动画返回原来位置，clone为true时才有效
      revert: Boolean,
      // 分组名称， 与my-drop配合使用
      group: String,
      // 是否禁用拖拽
      disabled: Boolean,
      // 附加数据
      data: [String, Number, Object, Array],
      // 克隆元素添加 className
      cloneClass: String,
      // 相对坐标原点, 默认自动获取
      origin: {
        type: [String, HTMLElement, Function],
        default() {
          return null
        }
      },
      // 克隆元素是否追加到body
      appendBody: Boolean
    },
    data() {
      // 非响应式数据定义
      this.handleEl = null
      this.dragEl = null
      this.cacheRange = null
      this.cacheOrigin = null

      return {
        // 是否正在拖拽
        dragging: false,
        // 是否拖动过
        dragged: false,
        // 拖拽元素相对原点的位置
        x: null,
        y: null,
        // 拖拽元素与鼠标的偏移位置
        offsetX: 0,
        offsetY: 0,
        // 开始拖拽时元素相对原点的位置
        startX: 0,
        startY: 0,
        // 拖拽鼠标坐标
        clientX: 0,
        clientY: 0,
        dropped: false
      }
    },
    computed: {
      classes() {
        return {
          'is-clone': this.clone,
          'is-dragging': this.dragging,
          'is-disabled': this.disabled,
          'is-dragged': this.dragged,
          'my-drag__handle': this.$el === this.handleEl
        }
      }
    },
    methods: {
      // 获取原点相对可视区位置
      getOrigin() {
        if (this.cacheOrigin) return this.cacheOrigin
        // 如果设置了origin，按origin取，否则就从DOM树向上查找定位元素，如无，就取documentElement
        const el = this.origin
          ? getElement(this.document, this.origin)
          : getRelativeEl(this.$el)
        this.cacheOrigin = el.getBoundingClientRect()

        return this.cacheOrigin

      },
      // 获取拖拽句柄
      getHandle() {
        if (!this.handle) {
          return this.$el
        }
        return getElement(this.$el, this.handle) || this.$el
      },
      // 获取拖拽范围目标元素
      getTarget() {
        if (!this.target) return null
        return getElement(this.document, this.target)
      },
      // 获取拖拽范围 {left,top, width, height}
      getRange() {
        if (this.cacheRange) {
          return this.cacheRange
        }
        const target = this.getTarget()
        if (target) {
          const rect = target.getBoundingClientRect()
          const elRect = this.$el.getBoundingClientRect()
          const origin = this.getOrigin()
          this.cacheRange = {
            left: rect.left - origin.left,
            top: rect.top - origin.top,
            width: rect.width - elRect.width,
            height: rect.height - elRect.height
          }
        } else {
          this.cacheRange = typeof this.range === 'function'
            ? this.range()
            : (this.range || DEFAULT_RANGE)
        }

        return this.cacheRange
      },
      // 创建拖拽元素
      createDragEl(e) {
        //  不设置克隆，拖拽元素就是组件根节点
        if (!this.clone) {
          this.dragEl = this.$el;
          return
        }

        if (typeof this.clone === 'function') {
          // 如果是函数，执行函数，返回元素对象
          this.dragEl = this.clone(this)
          if (!this.dragEl) {
            throw new Error('参数clone函数并没有返回正确的HTMLElement')
          }
        } else {
          // 克隆组件自己
          this.dragEl = this.$el.cloneNode(true)
        }
        addClass(this.dragEl, 'my-drag__clone')
        if (this.cloneClass) {
          addClass(this.dragEl, this.cloneClass)
        }
        if (this.appendBody) {
          this.document.body.appendChild(this.dragEl)
        } else {
          this.$el.parentNode.appendChild(this.dragEl)
        }
      },
      // 设置拖拽元素的开始时样式
      setDragElStyle() {
        if (!this.clone) return

        const style = {
          left: `${this.startX}px`,
          top: `${this.startY}px`,
          display: 'inline-block'
        }
        if (typeof this.clone === 'function') {
          style.display = 'inline-block'
        }
        setStyle(this.dragEl, style)

      },
      // 当拖拽没有成功放置，克隆拖拽的元素自动复原位置
      revertDragEl() {
        // 这个功能自动对克隆元素有效
        if (this.dragEl &amp;&amp; this.clone) {
          if (this.revert) {
            // 添加过渡动画样式
            addClass(this.dragEl, 'is-revert')
            setStyle(this.dragEl, {
              left: `${this.startX}px`,
              top: `${this.startY}px`
            })
            // 动画执行完成后，清除dom
            once(this.dragEl, 'webkitTransitionEnd', this.clearDragEl)
            once(this.dragEl, 'transitionend', this.clearDragEl)
            // 预防动画完成事件不触发，定时清除
            setTimeout(this.clearDragEl.bind(this), 300)
          } else {
            // 不设置克隆，立即清除dom
            this.clearDragEl()
          }
        }

      },
      // 清除克隆拖拽dom
      clearDragEl() {
        if (this.dragEl &amp;&amp; this.clone) {
          removeClass(this.dragEl, 'is-revert')
          this.dragEl.parentNode.removeChild(this.dragEl)
        }
        this.dragEl = null
      },
      // 更新鼠标与拖拽元素的偏移值
      updateOffset({clientX, clientY}) {
        // 自定义克隆拖拽元素
        if (this.clone &amp;&amp; typeof this.clone === 'function') {
          const size = getDomSize(this.dragEl)
          this.offsetX = size.width / 2
          this.offsetY = size.height / 2
        } else {
          const rect = this.$el.getBoundingClientRect()
          this.offsetX = clientX - rect.left
          this.offsetY = clientY - rect.top
        }
      },
      // 修正位置
      fixPosition(e) {
        const origin = this.getOrigin()
        if (this.appendBody) {
          return {
            x: e.pageX - this.offsetX,
            y: e.pageY - this.offsetY
          }
        } else {
          return {
            x: e.clientX - this.offsetX - origin.left,
            y: e.clientY - this.offsetY - origin.top
          }
        }
      },
      // 是否有my-resize子组件正在resizing
      isResizing() {
        return !!this.$children.find(item => {
          if (item.$options &amp;&amp; item.$options.name === 'MyResize') {
            return item.resizing
          }
        })
      },
      /**
       * 为了防止拖拽过程中鼠标选中了页面的文字导致 mouseup 事件不被触发，在开始拖拽时禁止页面选择文字，在停止拖拽后再恢复
       * @private
       * @param disabled 添加还是删除，true为添加
       */
      userSelect(disabled) {
        disabled
          ? addClass(this.document.body, 'user-select-none')
          : removeClass(this.document.body, 'user-select-none')
      },
      // 拖拽开始
      start(e) {
        this.cacheRange = null
        // 标识正在拖拽
        this.dragging = true
        // 初始化已放置，开始是未放置，这个属性的修改是在 my-drop 组件中修改为true
        this.dropped = false
        this.createDragEl(e)
        this.updateOffset(e)
        const position = this.fixPosition(e)
        this.startX = position.x
        this.startY = position.y
        this.setDragElStyle()
        this.userSelect(true)
        /**
         * 开始拖拽时触发
         * @event start
         * @param {VueComponent} vm MyDrag实例
         */
        this.$emit('start', this)
        bus.$emit('my-drag:start', this)

      },
      // 锁定拖拽方向
      lockAxis(x, y) {
        switch (this.axis) {
          case 'h':
            this.x = x
            break;
          case 'v':
            this.y = y
            break;
          default:
            this.x = x
            this.y = y
            break;
        }
      },
      // 锁定拖拽范围
      lockRange(x, y) {
        const range = this.getRange()
        this.x = x
        this.y = y
        if (x &lt; range.left) {
          this.x = range.left
        }
        if (y &lt; range.top) {
          this.y = range.top
        }
        if (x > range.left + range.width) {
          this.x = range.left + range.width
        }

        if (y > range.top + range.height) {
          this.y = range.top + range.height
        }

      },
      // 拖拽
      move({x, y}) {
        this.lockAxis(x, y)
        this.lockRange(this.x, this.y)
        setStyle(this.dragEl, {
          left: `${this.x}px`,
          top: `${this.y}px`
        })
        this.dragged = true
        /**
         * 拖拽中触发
         * @event drag
         * @param {VueComponent} vm MyDrag实例
         */
        this.$emit('drag', this)
        bus.$emit('my-drag:dragging', this)
      },
      // 停止拖拽
      stop() {
        /**
         * 结束拖拽时触发
         * @event stop
         * @param {VueComponent} vm MyDrag实例
         */
        this.$emit('stop', this)
        bus.$emit('my-drag:stop', this)
        // 已过成功放置，清除拖拽副本，否则就重置，dropped 在my-drop中更新，这行要放在触发stop事件之后
        this.dropped ? this.clearDragEl() : this.revertDragEl()
        // 清空缓存
        this.cacheRange = null
        this.cacheOrigin = null
        this.dragging = false
        this.userSelect(false)
      },
      handleMouseDown(e) {
        // 禁用不触发
        if (this.disabled) return
        // 为了防止点击的行为触发拖拽，加定时器
        this.timer = setTimeout(() => {
          // 如果有my-resize 子组件正在resizing， 禁止拖拽
          if (this.isResizing()) {
            return
          }
          this.start(e)
          on(this.document, 'mousemove', this.proxyMove)
        }, this.delay)

        once(this.document, 'mouseup', this.handleMouseUp)

      },
      handleMouseMove(e) {
        this.clientX = e.clientX
        this.clientY = e.clientY
        const position = this.fixPosition(e)
        this.move(position)

      },
      handleMouseUp() {
        clearTimeout(this.timer)
        off(this.document, 'mousemove', this.proxyMove)
        this.dragging &amp;&amp; this.stop()

      },
      // 绑定拖拽句柄
      bindHandle() {
        const handle = this.getHandle()
        addClass(handle, HANDLE_CLASS)
        on(handle, 'mousedown', this.handleMouseDown)
        this.handleEl = handle
      },
      // 解绑拖拽句柄
      unbindHandle() {
        if (this.handleEl) {
          removeClass(this.handleEl, HANDLE_CLASS)
          off(this.handleEl, 'mousedown', this.handleMouseDown)
          this.handleEl = null
        }
      }
    },
    created() {
      // 节流
      this.proxyMove = throttle(this.handleMouseMove, this)
    },
    mounted() {
      this.document = window.document
      this.bindHandle()
    },
    beforeDestroy() {
      clearTimeout(this.timer)
      this.unbindHandle()
      this.clearDragEl()
      this.document = null
    }
  }
&lt;/script>
</code></pre>
        </article>
    </section>





    
</div>

<br class="clear">

<footer>
    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.6.6</a> on Wed Nov 18 2020 13:00:34 GMT+0800 (GMT+08:00) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
</footer>

<script>prettyPrint();</script>
<script src="scripts/polyfill.js"></script>
<script src="scripts/linenumber.js"></script>




<script>
var _hmt = _hmt || [];
(function() {
  var hm = document.createElement("script");
  hm.src = "https://hm.baidu.com/hm.js?c4e5f73318b5cb0c389e3d9a05f831cc";
  var s = document.getElementsByTagName("script")[0];
  s.parentNode.insertBefore(hm, s);
})();
</script>

</body>
</html>
